﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;

namespace DnPakExplorer {

	/// <summary>
	/// 获取龙之谷资源数据的工具类，此类会缓存大量的资源数据（主要是二维表数据）
	/// </summary>
	public class DnResourceUtil {
		static List<Dntable> mPotencialTables;
		static List<Dntable> mEnchantTables;
		static List<Dntable> mPartsTables;
		static List<Dntable> mSetTables;
		static List<Dntable> mWeaponTables;
		static List<Dntable> mItemTables;
		static List<Dntable> mImprintingTables;
		static List<Dntable> mSkillLevelTables;
		static List<Dntable> mSkillTables;
		static Dntable mDranonJewelSlotsTable;
		static Dntable mDragonJewelTable;
		static Dntable mJobTable;
		static Dntable mPlayerCommonLevelTable;
		static Dntable mPlayerLevelTable;
		static Dntable mRebootPlayerWeightTable;
		static Dntable mHeroLevelTable;
		static Dntable mAppellationtable;
		static Dntable mVehiclePartsTable;
		static Dntable mVehicleTable;
		static Dntable mPetLevelTable;
		static Dntable mImprintingGuideTable;
		static Dntable mFairyTypeTable;
		static Dntable mFairyGrowLevelTable;

		static Hashtable mBufferedSetEntries = new Hashtable();
		static XmlDocument mConfigDocument;

		/// <summary>
		/// 保存和读取配置的Xml文档
		/// </summary>
		static public XmlDocument Config {
			get {
				if (mConfigDocument == null) {
					mConfigDocument = new XmlDocument();
					mConfigDocument.Load(@".\Data\config.xml");
				}
				return mConfigDocument;
			}
		}

		/// <summary>
		/// 物品数据表
		/// </summary>
		static public List<Dntable> ItemTables {
			get {
				if (mItemTables == null) {
					mItemTables = new List<Dntable>();
					foreach (XmlNode node in Config.SelectNodes(@"/Config/ItemTables/Table/@path")) {
						mItemTables.Add(Util.GetTable(node.InnerText));
					}
				}
				return mItemTables;
			}
		}

		/// <summary>
		/// 物品潜在属性数据表
		/// </summary>
		static public List<Dntable> PotencialTables {
			get {
				if (mPotencialTables == null) {
					mPotencialTables = new List<Dntable>();
					foreach (XmlNode node in Config.SelectNodes(@"/Config/PotentialTables/Table/@path")) {
						mPotencialTables.Add(Util.GetTable(node.InnerText));
					}
				}
				return mPotencialTables;
			}
		}

		/// <summary>
		/// 强化属性数据表
		/// </summary>
		static public List<Dntable> EnchantTables {
			get {
				if (mEnchantTables == null) {
					mEnchantTables = new List<Dntable>();
					foreach (XmlNode node in Config.SelectNodes(@"/Config/EnchantTables/Table/@path")) {
						mEnchantTables.Add(Util.GetTable(node.InnerText));
					}
				}
				return mEnchantTables;
			}
		}

		/// <summary>
		/// 部件数据表
		/// </summary>
		static public List<Dntable> PartsTables {
			get {
				if (mPartsTables == null) {
					mPartsTables = new List<Dntable>();
					foreach (XmlNode node in Config.SelectNodes(@"/Config/PartsTables/Table/@path")) {
						mPartsTables.Add(Util.GetTable(node.InnerText));
					}
				}
				return mPartsTables;
			}
		}

		/// <summary>
		/// 套装属性表
		/// </summary>
		static public List<Dntable> SetTables {
			get {
				if (mSetTables == null) {
					mSetTables = new List<Dntable>();
					foreach (XmlNode node in Config.SelectNodes(@"/Config/SetItemTables/Table/@path")) {
						mSetTables.Add(Util.GetTable(node.InnerText));
					}
				}
				return mSetTables;
			}
		}

		/// <summary>
		/// 武器数据表
		/// </summary>
		static public List<Dntable> WeaponTables {
			get {
				if (mWeaponTables == null) {
					mWeaponTables = new List<Dntable>();
					foreach (XmlNode node in Config.SelectNodes(@"/Config/WeaponTables/Table/@path")) {
						mWeaponTables.Add(Util.GetTable(node.InnerText));
					}
				}
				return mWeaponTables;
			}
		}

		/// <summary>
		/// 技能等级数据表
		/// </summary>
		static public List<Dntable> SkillLevelTables {
			get {
				if (mSkillLevelTables == null) {
					mSkillLevelTables = new List<Dntable>();
					foreach (XmlNode node in Config.SelectNodes(@"/Config/SkillLevelTables/Table/@path")) {
						mSkillLevelTables.Add(Util.GetTable(node.InnerText));
					}
				}
				return mSkillLevelTables;
			}
		}

		/// <summary>
		/// 技能数据表
		/// </summary>
		static public List<Dntable> SkillTables {
			get {
				if (mSkillTables == null) {
					mSkillTables = new List<Dntable>();
					foreach (XmlNode node in Config.SelectNodes(@"/Config/SkillTables/Table/@path")) {
						mSkillTables.Add(Util.GetTable(node.InnerText));
					}
				}
				return mSkillTables;
			}
		}

		/// <summary>
		/// 刻印数据表
		/// </summary>
		static public List<Dntable> ImprintingTables {
			get {
				if (mImprintingTables == null) {
					mImprintingTables = new List<Dntable>();
					foreach (XmlNode node in Config.SelectNodes(@"/Config/ImprintingTables/Table/@path")) {
						mImprintingTables.Add(Util.GetTable(node.InnerText));
					}
				}
				return mImprintingTables;
			}
		}

		/// <summary>
		/// 龙玉槽数据表
		/// </summary>
		static public Dntable DranonJewelSlotsTable {
			get {
				if (mDranonJewelSlotsTable == null) {
					mDranonJewelSlotsTable = Util.GetTable(@"\resource\ext\dragonjewelslottable.dnt");
				}
				return mDranonJewelSlotsTable;
			}
		}

		/// <summary>
		/// 龙玉数据表
		/// </summary>
		static public Dntable DragonJewelTable {
			get {
				if (mDragonJewelTable == null) {
					mDragonJewelTable = Util.GetTable(@"\resource\ext\dragonjeweltable.dnt");
				}
				return mDragonJewelTable;
			}
		}

		/// <summary>
		/// 职业数据表
		/// </summary>
		static public Dntable JobTable {
			get {
				if (mJobTable == null) {
					mJobTable = Util.GetTable(@"\resource\ext\jobtable.dnt");
				}
				return mJobTable;
			}
		}

		/// <summary>
		/// 共享的职业等级数据表
		/// </summary>
		static public Dntable PlayerCommonLevelTable {
			get {
				if (mPlayerCommonLevelTable == null) {
					mPlayerCommonLevelTable = Util.GetTable(@"\resource\ext\playercommonleveltable.dnt");
				}
				return mPlayerCommonLevelTable;
			}
		}

		/// <summary>
		/// 职业等级数据表
		/// </summary>
		static public Dntable PlayerLevelTable {
			get {
				if (mPlayerLevelTable == null) {
					mPlayerLevelTable = Util.GetTable(@"\resource\ext\playerleveltable.dnt");
				}
				return mPlayerLevelTable;
			}
		}

		/// <summary>
		/// 属性转化比率数据表
		/// </summary>
		static public Dntable RebootPlayerWeightTable {
			get {
				if (mRebootPlayerWeightTable == null) {
					mRebootPlayerWeightTable = Util.GetTable(@"\resource\ext\rebootplayerweighttable.dnt");
				}
				return mRebootPlayerWeightTable;
			}
		}

		/// <summary>
		/// 英雄等级数据表
		/// </summary>
		static public Dntable HeroLevelTable {
			get {
				if (mHeroLevelTable == null) {
					mHeroLevelTable = Util.GetTable(@"\resource\ext\heroleveltable.dnt");
				}
				return mHeroLevelTable;
			}
		}

		/// <summary>
		/// 称号数据表
		/// </summary>
		static public Dntable Appellationtable {
			get {
				if (mAppellationtable == null) {
					mAppellationtable = Util.GetTable(@"\resource\ext\appellationtable.dnt");
				}
				return mAppellationtable;
			}
		}

		/// <summary>
		/// 坐骑部件数据表
		/// </summary>
		static public Dntable VehiclePartsTable {
			get {
				if (mVehiclePartsTable == null) {
					mVehiclePartsTable = Util.GetTable(@"\resource\ext\vehiclepartstable.dnt");
				}
				return mVehiclePartsTable;
			}
		}

		/// <summary>
		/// 坐骑数据表
		/// </summary>
		static public Dntable VehicleTable {
			get {
				if (mVehicleTable == null) {
					mVehicleTable = Util.GetTable(@"\resource\ext\vehicletable.dnt");
				}
				return mVehicleTable;
			}
		}
		
		/// <summary>
		/// 宠物等级数据表
		/// </summary>
		static public Dntable PetLevelTable {
			get {
				if (mPetLevelTable == null) {
					mPetLevelTable = Util.GetTable(@"\resource\ext\petleveltable.dnt");
				}
				return mPetLevelTable;
			}
		}

		/// <summary>
		/// 刻印向导数据表
		/// </summary>
		static public Dntable ImprintingGuideTable {
			get {
				if (mImprintingGuideTable == null) {
					mImprintingGuideTable = Util.GetTable(@"\resource\ext\imprintingguidetable.dnt");
				}
				return mImprintingGuideTable;
			}
		}

		/// <summary>
		/// 精灵类型数据表
		/// </summary>
		static public Dntable FairyTypeTable {
			get {
				if (mFairyTypeTable == null) {
					mFairyTypeTable = Util.GetTable(@"\resource\ext\fairytypetable.dnt");
				}
				return mFairyTypeTable;
			}
		}

		/// <summary>
		/// 精灵成长数据表
		/// </summary>
		static public Dntable FairyGrowLevelTable {
			get {
				if (mFairyGrowLevelTable == null) {
					mFairyGrowLevelTable = Util.GetTable(@"\resource\ext\fairygrowleveltable.dnt");
				}
				return mFairyGrowLevelTable;
			}
		}

		/// <summary>
		/// 根据配置加载所有的数据表
		/// </summary>
		static public void LoadAllTables() {
			Dntable table = null;
			List<Dntable> list = null;

			table = DranonJewelSlotsTable;
			table = JobTable;
			table = PlayerCommonLevelTable;
			table = PlayerLevelTable;
			table = RebootPlayerWeightTable;

			list = ItemTables;
			list = PotencialTables;
			list = EnchantTables;
			list = PartsTables;
			list = SetTables;
			list = WeaponTables;
			list = SkillLevelTables;
			list = SkillTables;
		}

		/// <summary>
		/// 通过物品id查找物品的名称
		/// </summary>
		/// <param name="preferedTable">休闲查找的物品数据表</param>
		static private string GetItemName(int itemId, Dntable preferedTable) {
			int c;
			Dntable table = preferedTable;
			for (int r=0; r<table.RecordCount; r++) {
				if (itemId == table.GetKey(r)) {
					string s = Util.FindUIString(((int)table[r, 0]));
					if (s != null) {
						string nameParams = (string)table[r, 2];
						if (nameParams != "") {
							s = string.Format(s, Util.parseParams3(nameParams, out c));
						}
					}
					return s;
				}
			}

			foreach (Dntable itemTable in ItemTables) {
				if (itemTable == preferedTable)
					continue;
				for (int r=0; r<table.RecordCount; r++) {
					if (itemId == table.GetKey(r)) {
						string s = Util.FindUIString(((int)table[r, 0]));
						if (s != null) {
							string nameParams = (string)table[r, 2];
							if (nameParams != "") {
								s = string.Format(s, Util.parseParams3(nameParams, out c));
							}
						}
						return s;
					}
				}
			}
			return null;
		}

		//static private void GetSet(Dntable table, int r, int setIdField, int setTextIdField, IUserItem skill) {
		//	int setID = (int)table[r, setIdField];
		//	if (setID <=0)
		//		return;
		//	SetEntry set = mBufferedSetEntries[setID] as SetEntry;
		//	if (set != null) {
		//		skill.set = set;
		//		return;
		//	}
		//	mBufferedSetEntries[setID] = skill.set = set = new SetEntry();
		//		set.setItems = new List<IUserItem>();
		//	set.setID = setID;
		//	for (int row=r-1; row>=0; row--) {
		//		if ((int)table[row, setIdField] == set.setID) {
		//			set.setItems.Add(DnResourceUtil.LoadItem(table.GetKey(row), skill.fromTable));
		//		} else
		//			break;
		//	}
		//	set.setItems.Add(new IUserItem(skill.fromTable, skill.c));
		//	int textId = (int)table[r, setTextIdField];
		//	if (textId > 0) {
		//		set.setDescription = Util.FindUIString(textId);
		//	}
		//	for (int row=r+1; row<table.RecordCount; row++) {
		//		if ((int)table[row, setIdField] == set.setID) {
		//			set.setItems.Add(DnResourceUtil.LoadItem(table.GetKey(row), skill.fromTable));
		//		} else
		//			break;
		//	}
		//}


		//static public void GetSet(IUserItem skill) {
		//	int setIdField = 47;
		//	int setTextIdField = 56;
		//	foreach (Dntable table in PartsTables) {
		//		for (int r=0; r<table.RecordCount; r++) {
		//			if (table.GetKey(r) == skill.id) {
		//				GetSet(table, r, setIdField, setTextIdField, skill);

		//				return;
		//			}
		//		}
		//	}
		//	setIdField = 30;
		//	setTextIdField = 54;
		//	foreach (Dntable table in WeaponTables) {
		//		for (int r=0; r<table.RecordCount; r++) {
		//			if (table.GetKey(r) == skill.id) {
		//				GetSet(table, r, setIdField, setTextIdField, skill);
		//				break;
		//			}
		//		}
		//	}
		//}

		/// <summary>
		/// 获取物品的套装属性描述及其套装Id
		/// </summary>
		/// <param name="item"></param>
		/// <param name="setDescription">输出参数：套装描述，如果物品没有相关的套装则返回null</param>
		/// <returns>套装id，如果物品没有相关的套装则返回-1</returns>
		static public int GetSetId(IItem item, out string setDescription) {
			setDescription = null;
			int itemId = item.id;
			if (item.exchangType == ItemType.Weapon1
				|| item.exchangType == ItemType.Weapon1Cash
				|| item.exchangType == ItemType.Weapon2
				|| item.exchangType == ItemType.Weapon2Cash) {
				int setIdField = 30;
				int setTextIdField = 54;
				foreach (Dntable table in WeaponTables) {
					for (int r=0; r<table.RecordCount; r++) {
						if (table.GetKey(r) == itemId) {
							int textId = (int)table[r, setTextIdField];
							if (textId > 0) {
								setDescription = Util.FindUIString(textId);
							}
							return (int)table[r, setIdField];
						}
					}
				}
			} else if (item.exchangType == ItemType.Vehicle) {
				int setIdField = 7;
				int setTextIdField = 9;
				Dntable table = VehiclePartsTable;
				for (int r=0; r<table.RecordCount; r++) {
					if (table.GetKey(r) == itemId) {
						int textId = (int)table[r, setTextIdField];
						if (textId > 0) {
							setDescription = Util.FindUIString(textId);
						}
						return (int)table[r, setIdField];
					}
				}
			} else {
				int setIdField = 47;
				int setTextIdField = 56;
				foreach (Dntable table in PartsTables) {
					for (int r=0; r<table.RecordCount; r++) {
						if (table.GetKey(r) == itemId) {
							int textId = (int)table[r, setTextIdField];
							if (textId > 0) {
								setDescription = Util.FindUIString(textId);
							}
							return (int)table[r, setIdField];
						}
					}
				}
			}
			
			
			return -1;
		}

		/// <summary>
		/// 解析物品套装，
		/// </summary>
		static public void GetSet(IItem item) { 
			string setDesc;
			int setId = GetSetId(item, out setDesc);
			if (setId > 0) {
				SetEntry set = mBufferedSetEntries[setId] as SetEntry;
				if (set != null) {
					item.set = set;
					return;
				}
				mBufferedSetEntries[setId] = item.set = set = new SetEntry();
				set.setID = setId;
				set.setDescription = setDesc;
				set.setItems = new List<IItem>();

				
				foreach (Dntable table in PartsTables) {
					bool found = false;
					for (int r=0; r<table.RecordCount; r++) {
						if ((int)table[r, 47] == setId) {
							if (item is Item)
								item.set.setItems.Add(DnResourceUtil.LoadItem(table.GetKey(r), ((Item)item).fromTable));
							else
								item.set.setItems.Add(DnResourceUtil.LoadItem(table.GetKey(r)));
							found = true;
						} 
					}
					if (found)
						break;
				}
				foreach (Dntable table in WeaponTables) {
					bool found = false;
					for (int r=0; r<table.RecordCount; r++) {
						if ((int)table[r, 30] == setId) {
							if (item is Item)
								item.set.setItems.Add(DnResourceUtil.LoadItem(table.GetKey(r), ((Item)item).fromTable));
							else
								item.set.setItems.Add(DnResourceUtil.LoadItem(table.GetKey(r)));
							found = true;
						}
					}
					if (found)
						break;
				}
			}
		}

		/// <summary>
		/// 获取通过职业id获取职业名
		/// </summary>
		/// <returns>如果没有相应的职业则返回null</returns>
		static public string GetJobName(int jobId) {
			for (int r=0; r<DnResourceUtil.JobTable.RecordCount; r++) {
				if (jobId == DnResourceUtil.JobTable.GetKey(r))
					return Util.FindUIString((int)DnResourceUtil.JobTable[r, "_JobName"]);
			}
			return null;
		}

		/// <summary>
		/// 获取龙玉物品的龙玉类型
		/// </summary>
		static public DragonJewelType GetDragonJewelType(int itemId) {
			int index = DragonJewelTable.IndexOfKey(itemId);
			if (index>=0) {
				return (DragonJewelType)DragonJewelTable[index, 0];
			}
			return DragonJewelType.None;
		}

		/// <summary>
		/// 获取刻印类型名称
		/// </summary>
		/// <returns>如果没有相关类型刻印则返回空字符串</returns>
		static public string GetImprintTypeName(ImprintingType type) {
			Dntable table = ImprintingGuideTable;
			string s = null;
			for (int r = 0; r<table.RecordCount; r++) {
				if ((ImprintingType)(int)table[r, 0] == type) {
					s = Util.FindUIString((int)table[r, 1]);
				}
			}
			if (s == null)
				s = "";
			return s;
		}

		/// <summary>
		/// 获取潜在属性组
		/// </summary>
		/// <param name="potencialKey">潜在属性组id</param>
		/// <param name="list">用于保存查询属性结果的列表</param>
		static public void GetPotencialProperties(int potencialKey, List<Property> list){
			foreach (Dntable table in DnResourceUtil.PotencialTables) {
				int row = -1;
				for (int r=0; r<table.RecordCount; r++) {
					if (table.GetKey(r) == potencialKey) {
						row = r;
						break;
					}
				}
				if (row>=0) {
					for (int i=4; i<34; i++) {
						Property prop = new Property();
						prop.id = (PropertyID)table[row, i++];
						if (prop.id < 0)
							break;
						string value = (string)table[row, i];
						if (Util.StateVlauePettern.IsMatch(value)) {
							prop.value = float.Parse(value);
							if (prop.value == 0) {
								continue;
							}
						} else {
							break;
						}
						list.Add(prop);
					}
					break;
				}
			}
		}

		static public void GetFirstPotencialProperties(int potencialId, List<Property> list) {
			foreach (Dntable table in DnResourceUtil.PotencialTables) {
				int row = -1;
				for (int r=0; r<table.RecordCount; r++) {
					if ((int)table[r, 0] == potencialId) {//905969914
						row = r;
						break;
					}
				}
				if (row>=0) {
					for (int i=4; i<34; i++) {
						Property prop = new Property();
						prop.id = (PropertyID)table[row, i++];
						if (prop.id < 0)
							break;
						string value = (string)table[row, i];
						if (Util.StateVlauePettern.IsMatch(value)) {
							prop.value = float.Parse(value);
						} else {
							prop.value = float.NaN;
							break;
						}
						list.Add(prop);
					}
					break;
				}
			}
		}

		/// <summary>
		/// 获取技能描述
		/// </summary>
		/// <param name="skillId">技能id</param>
		/// <param name="skillLevel">技能等级</param>
		/// <returns>如果描述未找到则返回"Description Not Found"</returns>
		static public string GetSkillDescription(int skillId, int skillLevel) {
			foreach (Dntable table in DnResourceUtil.SkillLevelTables) {
				for (int r = 0; r < table.RecordCount; r++) {
					if ((int)table[r, 0] == skillId && (int)table[r, 1]==skillLevel) {
						int id = (int)table[r, 19];
						if (id == 0) {
							return "";
						}
						string s = Util.FindUIString(id);
						string nameParams = (string)table[r, 20];
						int c;
						if (nameParams != "") {
							try {
								s = string.Format(s, Util.parseParams3(nameParams, out c));
							} catch (FormatException) {
							}
						}
						return s == null?"uis:" + id:s;
					}
				}
			}
			return "Description Not Found";
		}

		/// <summary>
		/// 获取技能名称
		/// </summary>
		/// <param name="skillId">技能id</param>
		static public string GetSkillName(int skillId) {
			foreach (Dntable table in DnResourceUtil.SkillTables) {
				int skillRow = table.IndexOfKey(skillId);
				if (skillRow >= 0) {
					int id = (int)table[skillRow, 0];
					if (id > 0) {
						string s = Util.FindUIString(id);
						return s == null?"uis:" + id:s;
					} else {
						return "";
					}
				}
			}
			return "Skill:"+skillId;
		}

		/// <summary>
		/// 加载物品
		/// </summary>
		/// <param name="itemId">要加载的物品的id</param>
		/// <returns>没有找到指定物品返回null</returns>
		public static IItem LoadItem(int itemId) {
			foreach (Dntable table in ItemTables) {
				for (int r=0; r<table.RecordCount; r++) {
					if (table.GetKey(r) == itemId) {
						return new Item(table, r);
					}
				}
			}
			return null;
		}

		/// <summary>
		/// 加载物品
		/// </summary>
		/// <param name="itemId">要加载的物品的id</param>
		/// <param name="preferedTable">优先查找的物品数据表</param>
		/// <returns>没有找到指定物品返回null</returns>
		public static IItem LoadItem(int itemId, Dntable preferedTable) {
			for (int r=0; r<preferedTable.RecordCount; r++) {
				if (preferedTable.GetKey(r) == itemId) {
					return new Item(preferedTable, r);
				}
			}
			foreach (Dntable table in ItemTables) {
				if (table == preferedTable)
					continue;
				for (int r=0; r<table.RecordCount; r++) {
					if (table.GetKey(r) == itemId) {
						return new Item(table, r);
					}
				}
			}
			return null;
		}

		/// <summary>
		/// 加载技能
		/// </summary>
		/// <param name="skillId">要加载的技能的id</param>
		/// <returns>如果没有找到指定技能则返回null</returns>
		public static Skill LoadSkill(int skillId) {
			foreach (Dntable table in SkillTables) {
				int row = table.IndexOfKey(skillId);
				if (row >= 0) {
					return new Skill(row, table);
				}
			}
			return null;
		}

		/// <summary>
		/// 加载一个初始的用户物品，此物品还没有用户做过任何设置或处理，无需用户数据就能加载
		/// </summary>
		/// <param name="itemId">要加载的用户物品对应物品id</param>
		/// <returns>如果没有找到指定物品则返回null</returns>
		public static IUserItem LoadEmptyUserItem(int itemId) {
			foreach (Dntable table in ItemTables) {
				for (int r=0; r<table.RecordCount; r++) {
					if (table.GetKey(r) == itemId) {
						return new UserItem(table, r);
					}
				}
			}
			return null;
		}

		/// <summary>
		/// 加载一个初始的用户物品
		/// </summary>
		/// <param name="itemId">要加载的用户物品对应物品id</param>
		/// <param name="itemId">休闲查找物品数据表</param>
		/// <returns>如果没有找到指定物品则返回null</returns>
		public static IUserItem LoadEmptyUserItem(int itemId, Dntable preferedTable) {
			for (int r=0; r<preferedTable.RecordCount; r++) {
				if (preferedTable.GetKey(r) == itemId) {
					return new UserItem(preferedTable, r);
				}
			}
			foreach (Dntable table in ItemTables) {
				if (table == preferedTable)
					continue;
				for (int r=0; r<table.RecordCount; r++) {
					if (table.GetKey(r) == itemId) {
						return new UserItem(table, r);
					}
				}
			}
			return null;
		}
	}

	
}
